package com.laizhenghua.demo.service.impl;

import com.laizhenghua.demo.service.CacheService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;


@ConditionalOnProperty(name = "data.type", havingValue = "memory")
@Service
public class MemoryCacheServiceImpl implements CacheService {
    private static final Map<String, String> DATA_MAP = new ConcurrentHashMap<>();

    private static final Map<String, Long> EXPIRE_MAP = new ConcurrentHashMap<>();

    private static final long ONE_MILLISECONDS = 1L;

    private static final long ONE_SECOND = ONE_MILLISECONDS * 1000;

    private static final long ONE_MINUTE = ONE_SECOND * 60;

    private static final long ONE_HOUR = ONE_MINUTE * 60;

    private static final long ONE_DAY = ONE_HOUR * 24;

    private static final Map<TimeUnit, Long> UNIT_LONG_MAP = new HashMap<>();

    static {
        UNIT_LONG_MAP.put(TimeUnit.DAYS, ONE_DAY);
        UNIT_LONG_MAP.put(TimeUnit.HOURS, ONE_HOUR);
        UNIT_LONG_MAP.put(TimeUnit.MINUTES, ONE_MINUTE);
        UNIT_LONG_MAP.put(TimeUnit.SECONDS, ONE_SECOND);
        UNIT_LONG_MAP.put(TimeUnit.MILLISECONDS, ONE_MILLISECONDS);
    }


    @Override
    public void set(String key, String value, long timeout, TimeUnit unit) {
        Long milliseconds = UNIT_LONG_MAP.get(unit);
        if (milliseconds == null) {
            throw new IllegalArgumentException("时间单位不支持");
        }
        long currentTime = System.currentTimeMillis();
        EXPIRE_MAP.put(key, currentTime + milliseconds * timeout);
        DATA_MAP.put(key, value);
    }

    @Override
    public String get(String key) {
        String value = DATA_MAP.get(key);
        if (value != null) {
            long expireTime = EXPIRE_MAP.get(key);
            if (System.currentTimeMillis() < expireTime) {
                return value;
            }
        }
        return null;
    }
}
